using System;
using SmartPeople.Framework.SecuritySpace;

namespace SmartPeople.Framework.SecuritySpace
{
    public sealed class SecurityRoles : ISecurityRoleProvider
    {
        private ISecurityRoleProvider provider;


        public SecurityRoles(ISecurityRoleProvider provider)
        {
            this.provider = provider;
        }


        private ISecurityRoleProvider Provider
        {
            get { return provider; }
            set { provider = value; }
        }

        public int Count
        {
            get { return Provider.Count; }
        }

        #region CreateRole

        public ISecurityRole CreateRole(string roleName)
        {
            Validate(roleName);
            return Provider.CreateRole(roleName);
        }

        #endregion

        #region CreateRole

        public ISecurityRole CreateRole(string roleName, string description, string comment)
        {
            Validate(roleName);
            return Provider.CreateRole(roleName, description, comment);
        }

        #endregion

        public ISecurityRole CreateRole(Guid roleGuid)
        {
            return Provider.CreateRole(roleGuid);
        }

        #region Validate

        private void Validate(string roleName)
        {
            ValidateRoleName(roleName);
        }

        #endregion

        #region ValidateRoleName

        private void ValidateRoleName(string roleName)
        {
            if (roleName.Length <= 1)
            {
                throw new ArgumentException("Role Name must be greater than five characters", GetType().FullName);
            }

            if (IsNumeric(roleName))
            {
                throw new ArgumentException("Role Name not be numeric", GetType().FullName);
            }
        }

        #endregion

        #region IsNumeric

        internal static bool IsNumeric(string numberString)
        {
            if (numberString == string.Empty) return false;

            char[] ca = numberString.ToCharArray();
            for (int i = 0; i < ca.Length; i++)
            {
                if (!char.IsNumber(ca[i]))
                    return false;
            }
            return true;
        }

        #endregion

        #region GetAllRoles

        public ISecurityRole[] GetAllRoles()
        {
            return Provider.GetAllRoles();
        }

        #endregion

        #region GetRole

        public ISecurityRole GetRole(string roleName)
        {
            return Provider.GetRole(roleName);
        }

        #endregion

        #region GetRoles

        public ISecurityRole[] GetRoles(string[] roleNames)
        {
            return Provider.GetRoles(roleNames);
        }

        public ISecurityRole GetRole(Guid roleguid)
        {
            return Provider.GetRole(roleguid);
        }

        #endregion

        #region UpdateRole

        public void UpdateRole(ISecurityRole role)
        {
            Provider.UpdateRole(role);
        }

        #endregion

        #region RoleExists

        public bool RoleExists(string roleName)
        {
            return provider.RoleExists(roleName);
        }

        public bool RoleExists(Guid roleGuid)
        {
            return provider.RoleExists(roleGuid);
        }

        #endregion

        #region DeleteRole(string roleName)

        public bool DeleteRole(string roleName)
        {
            ISecurityRole currentRole = GetRole(roleName);
            if (currentRole != null)
            {
                if (currentRole.IsReadOnly)
                {
                    throw new ArgumentException("Cannot delete system created role:" + roleName + "!");
                }
            }


            return Provider.DeleteRole(roleName);
        }

        #endregion

        #region DeleteRole(string roleName, bool throwOnPopulatedRole)

        public bool DeleteRole(string roleName, bool throwOnPopulatedRole)
        {
            ISecurityRole currentRole = GetRole(roleName);
            if (currentRole != null)
            {
                if (currentRole.IsReadOnly)
                {
                    throw new ArgumentException("Cannot delete system created role:" + roleName + "!");
                }
            }

            if (throwOnPopulatedRole)
            {
                if (GetUsersInRole(roleName).Length > 0)
                {
                    throw new ArgumentException("Cannot delete role as users exits for role!", GetType().ToString());
                }
            }

            return Provider.DeleteRole(roleName, throwOnPopulatedRole);
        }

        #endregion

        #region AddUsersToRoles

        public void AddUsersToRoles(string[] usernames, string[] roleNames)
        {
            Provider.AddUsersToRoles(usernames, roleNames);
        }

        #endregion

        #region RemoveUsersFromRoles

        public void RemoveUsersFromRoles(string[] userNames, string[] roleNames)
        {
            Provider.RemoveUsersFromRoles(userNames, roleNames);
        }

        #endregion

        #region GetRolesForUser

        public string[] GetRolesForUser(string userName)
        {
            return Provider.GetRolesForUser(userName);
        }

        public string[] GetRolesForUser(IToken userToken)
        {
            return Provider.GetRolesForUser(userToken);
        }

        #endregion

        #region GetUsersInRole

        public string[] GetUsersInRole(string roleName)
        {
            return Provider.GetUsersInRole(roleName);
        }

        #endregion

        #region IsUserInRole

        public bool IsUserInRole(string userName, string roleName)
        {
            return Provider.IsUserInRole(userName, roleName);
        }

        #endregion

        #region Clear

        public void Clear()
        {
            Provider.Clear();
        }

        #endregion
    }
}